/**
 * @file eigen_test.h
 *
 * Convenient tools for facilitating the test of Eigen-based functions
 * 
 * @author Dahua Lin
 */

#ifndef SLIPP_EIGEN_TEST_H_
#define SLIPP_EIGEN_TEST_H_

#include <slipp/eigen_ex/eigen_common.h>
#include <slipp/base/lang_utils.h>

namespace sli { namespace test {


	template<typename T>
	T safe_abs_diff(const T& x, const T& y)
	{
		return x > y ? x - y : y - x;
	}


	template<class Derived1, class Derived2>
	bool test_equal(const Eigen::DenseBase<Derived1>& a, const Eigen::DenseBase<Derived2>& b)
	{
		typedef typename Eigen::DenseBase<Derived1>::Scalar scalar_type;
		static_assert(is_same<typename Eigen::DenseBase<Derived2>::Scalar, scalar_type>::value,
				"test_approx: input arrays must be of the same scalar type.");

		if (a.rows() == b.rows() && a.cols() == b.cols())
		{
			index_t n = a.size();
			for (index_t i = 0; i < n; ++i)
			{
				if (a(i) != b(i)) return false;
			}
			return true;
		}
		else
		{
			return false;
		}
	}

	template<class Derived1, class Derived2>
	bool test_approx(const Eigen::DenseBase<Derived1>& a, const Eigen::DenseBase<Derived2>& b,
			const typename Eigen::DenseBase<Derived1>::Scalar& tol)
	{
		typedef typename Eigen::DenseBase<Derived1>::Scalar scalar_type;
		static_assert(is_same<typename Eigen::DenseBase<Derived2>::Scalar, scalar_type>::value,
				"test_approx: input arrays must be of the same scalar type.");

		if (a.rows() == b.rows() && a.cols() == b.cols())
		{
			index_t n = a.size();
			for (index_t i = 0; i < n; ++i)
			{
				scalar_type ad = safe_abs_diff(a(i), b(i));
				if (ad > tol) return false;
			}
			return true;
		}
		else
		{
			return false;
		}
	}


} }

#endif 
